package com.smasher.dialog

import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity

class DialogHelper {

    /**
     * 显示DialogFragment  默认使用反射无参数构造dialogFragment
     * @param activity activity
     * @param clazz clazz
     * @param args args
     * @param creator creator
     * @param initializer initializer
     */
    fun <T : DialogFragment> showDialog(
        activity: FragmentActivity,
        clazz: Class<T>,
        args: Bundle = Bundle(),
        creator: ((Class<T>, Bundle) -> T) = { clazzTemp, argsTemp -> createDialog(clazzTemp) },
        initializer: (dialog: DialogFragment) -> Unit
    ) {
        val supportFragmentManager = activity.supportFragmentManager
        var dialog = supportFragmentManager.findFragmentByTag(clazz.simpleName)
        if (dialog == null) {
            dialog = creator.invoke(clazz, args)
        }
        if (dialog is DialogFragment) {
            initializer.invoke(dialog)
            if (!isShowing(dialog)) {
                dialog.show(supportFragmentManager, clazz.simpleName)
            }
        }
    }

    /**
     * 隐藏DialogFragment
     * @param activity activity
     * @param clazz clazz
     */
    fun <T : DialogFragment> hideDialog(activity: FragmentActivity, clazz: Class<T>) {
        val supportFragmentManager = activity.supportFragmentManager
        val dialog = supportFragmentManager.findFragmentByTag(clazz.simpleName)
        if (dialog is DialogFragment) {
            if (isShowing(dialog)) {
                dialog.dismiss()
            }
        }
    }

    /**
     * 默认无参构造
     */
    fun <Dialog : DialogFragment> createDialog(clazz: Class<Dialog>): Dialog {
        return try {
            // 1. 构造方法校验
            val constructor = clazz.getDeclaredConstructor().apply {
                isAccessible = true // 允许访问非public构造
            }
            // 2. 安全实例化
            constructor.newInstance()
        } catch (e: NoSuchMethodException) {
            throw IllegalArgumentException("${clazz.simpleName} must have a no-arg constructor", e)
        } catch (e: Exception) {
            throw RuntimeException("Dialog instantiation failed", e)
        }
    }

    private fun <Dialog : DialogFragment> isShowing(dialog: Dialog): Boolean {
        return dialog.dialog?.isShowing == true
    }

}